#ifndef __CAM_TELE_H__
#define __CAM_TELE_H__

#include <functional>

#include "base.pb.h"
#include "camera.pb.h"
#include "rkmedia_buffer.h"
#include "rkmedia_common.h"
#include "rk_camera.h"
#include "sample_common.h"
#include "notify.pb.h"
#include "params_setting.h"

#include <opencv2/opencv.hpp>

using namespace std;

void getJgpFrame(uint8_t* &frame, int &frame_size, unsigned int &frame_id);
int matToByteArray(const cv::Mat& mat, int jpg_quality = 100);
int setImgRaw(const cv::Mat& img_raw);
int getProcessedRaw(cv::Mat& processed_raw_8b);

struct CamTeleParamsT {
    opMode_t exp_mode = (opMode_t)0;
    double exp = 0.03;
    int gain = 0;
    int ircut = 0;
    opMode_t wb_mode = (opMode_t)0;
    rk_aiq_wb_scene_t wb_scene = (rk_aiq_wb_scene_t)-1;
    RK_U32 wb_ct = 4500;
    RK_U32 brightness = 128;
    RK_U32 contrast = 128;
    RK_U32 saturation = 128;
    RK_U32 hue = 128;
    RK_U32 sharpness = 50;
    int jpg_quality = 60;
};

class CamTele {
public:
     CamTele();
    ~CamTele();

    int openCamera(bool binning);
    int closeCamera();
    int photograph(std::string file_name);
    int burstPhotograph(int count);
    int stopBurstPhoto();
    int startRecord(bool notify = true);
    int stopRecord(bool notify = true);

    int handleMessage(WsPacket& ws_packet);
    int openCamera(WsPacket& ws_packet);
    int closeCamera(WsPacket& ws_packet);
    int photograph(WsPacket& ws_packet);
    int burstPhotograph(WsPacket& ws_packet);
    int stopBurstPhoto(WsPacket& ws_packet);
    int startRecord(WsPacket& ws_packet);
    int stopRecord(WsPacket& ws_packet);
    int startTimeLapsePhotograph(WsPacket& ws_packet);
    int stopTimeLapsePhotograph(WsPacket& ws_packet);
    int stopTimeLapsePhotograph();

    int isCameraOpen();
    int isCameraClose();
    bool getCameraState();
    void setCameraState(bool state);
    bool getBinningState();
    void setBinningState(bool state);
    static void setPhotoState(CamTelePhotoState mode);
    static CamTelePhotoState getPhotoState();
    void setRecordState(CamTeleRecordState state);
    CamTeleRecordState getRecordState();
    void setTimelapseState(CamTeleTimelapseState state);
    static CamTeleTimelapseState getTimelapseState();
    void setPanoramaState(CamTelePanoramaState state);
    CamTelePanoramaState getPanoramaState();


    void getNv12MediaBufferWithID(MEDIA_BUFFER* buffer, uint64_t* frame_id);
    MEDIA_BUFFER getNv12MediaBuffer();
    MEDIA_BUFFER getNewestNv12MediaBuffer();
    MEDIA_BUFFER getRgbMB_720p(int target_width, int target_height, bool block = false);
    MEDIA_BUFFER getNv12MediaBufferByPass();
    MEDIA_BUFFER getNewestNv12MediaBufferByPass();
    MEDIA_BUFFER getRgbMB_4k(int target_width, int target_height, bool block = false);
    
    //isp
    int setExpMode(int mode);
    int getExpMode(opMode_t *mode);
    int setExp(double value);
    int setGainMode(int mode);
    int getGainMode(int *mode);
    int setGain(int value);
    int getExp(double *value);
    int getGain(int *value);
    int setIrCut(int value);
    int getIrCut(int *value);
    int setWBMode(opMode_t mode);
    int getWBMode(opMode_t *mode);
    int setWBScene(rk_aiq_wb_scene_t scene);
    int getWBScene(rk_aiq_wb_scene_t *scene);
    int setWBCT(int value);
    int getWBCT(RK_U32 *value);
    int setBrightness(RK_U32 value);
    int getBrightness(RK_U32 *value);
    int setContrast(RK_U32 value);
    int getContrast(RK_U32 *value);
    int setSaturation(RK_U32 value);
    int getSaturation(RK_U32 *value);
    int setHue(RK_U32 value);
    int getHue(RK_U32 *value);
    int setSharpness(RK_U32 value);
    int getSharpness(RK_U32 *value);

    int getExp(ExposureSetting& exp_setting);
    int getGain(IntValueSetting& gain_setting);

    int setExpMode(WsPacket& ws_packet);
    int getExpMode(WsPacket& ws_packet);
    int setExp(WsPacket& ws_packet);
    int setGainMode(WsPacket& ws_packet);
    int getGainMode(WsPacket& ws_packet);
    int setGain(WsPacket& ws_packet);
    int getExp(WsPacket& ws_packet);
    int getGain(WsPacket& ws_packet);

    int setBrightness(WsPacket& ws_packet);
    int setContrast(WsPacket& ws_packet);
    int setSaturation(WsPacket& ws_packet);
    int setHue(WsPacket& ws_packet);
    int setSharpness(WsPacket& ws_packet);
    int setWBMode(WsPacket& ws_packet);
    int getWBMode(WsPacket& ws_packet);
    int setWBScene(WsPacket& ws_packet);
    int getWBScene(WsPacket& ws_packet);
    int setWBCT(WsPacket& ws_packet);
    int getWBCT(WsPacket& ws_packet);
    int setIrCut(WsPacket& ws_packet);
    int getIrCut(WsPacket& ws_packet);

    int getBrightness(WsPacket& ws_packet);
    int getContrast(WsPacket& ws_packet);
    int getSaturation(WsPacket& ws_packet);
    int getHue(WsPacket& ws_packet);
    int getSharpness(WsPacket& ws_packet);

    int setAllParams(int exp_mode, int exp_index, int gain_mode, int gain_index, int ircut_value, int wb_mode,
                        int wb_index_type, int wb_index, int brightness, int contrast, int hue, int saturation, int sharpness, int jpg_quality);
    int setAllParams(WsPacket& ws_packet);
    int getAllParams(WsPacket& ws_packet);
    int setJpgQuality(int jpg_quality);
    int getJpgQuality();
    int setJpgQuality(WsPacket& ws_packet);
    int setFeatureParam(WsPacket& ws_packet);
    int getAllFeatureParams(WsPacket& ws_packet);
    int getSystemWorkingState(WsPacket& ws_packet);

    // 抓RAW图
    int startCaptureRaw(WsPacket& ws_packet);
    int startCaptureRaw(const cv::Size& img_size, int img_to_take);
    void exitCaptureRaw();
    void stopCaptureRaw();
    inline void setCaptureRawCallback(const function<int(const cv::Mat& img, const std::string& date_obs, int img_count)>& captureRawCallback) { 
        captureRawCallback_ = captureRawCallback; 
    }
    inline void setCaptureRawDoneCallback(const function<void()>& captureRawDoneCallback) { 
        captureRawDoneCallback_ = captureRawDoneCallback; 
    }
    const cv::Size& imgSize2k();
    const cv::Size& imgSize4k();
    int notifyPictureMatchingResult();

    int initRKmedia();
    int getAllParams();
    int getRecordLoadingCount();

private:
    int initCamera(bool binning);
    int initViChannel(bool binning);
    int initVencChannel(bool binning);
    static void jpgPreviewOutCb(MEDIA_BUFFER mb);
    static void jpgPhotoOutCb(MEDIA_BUFFER mb);

    void getMediaBuffer();
    void timeLapseGetMediaBuffer();
    void getMediaBufferBypass();

private:
    function<int(const cv::Mat& img, const std::string& date_obs, int img_count)> captureRawCallback_ = nullptr;
    function<void()> captureRawDoneCallback_ = nullptr;
};


#endif